Skip to content

Add copy-as-HAR buttons for captured requests - #38

Merged
botre merged 1 commit into
masterfrom
feat/copy-requests-as-har
Aug 8, 2026
Merged

Add copy-as-HAR buttons for captured requests#38
botre merged 1 commit into
masterfrom
feat/copy-requests-as-har

Conversation

@botre

@botre botre commented Aug 8, 2026

Copy link
Copy Markdown
Collaborator

What

Adds two clipboard actions on the endpoint screen:

  • Copy request — per card, next to Delete.
  • Copy all (N) — page level, next to Delete all.

Both put a HAR-shaped JSON document on the clipboard containing everything about the request: method, URL, headers, query string and body. Same envelope either way, so consumers parse one shape regardless of which button was used.

{
  "creator": { "name": "httphq", "version": "1" },
  "entries": [
    {
      "id": "0625b960-0143-4163-99cb-72484269ab09",
      "startedDateTime": "2026-08-08T08:55:00.809Z",
      "clientIPAddress": "127.0.0.1",
      "request": {
        "method": "GET",
        "url": "http://localhost:8080/to/demo-har-panel?utm_source=newsletter&plan=pro",
        "httpVersion": "HTTP/1.1",
        "headers": [{ "name": "X-Api-Key", "value": "sk_test_123" }],
        "queryString": [{ "name": "utm_source", "value": "newsletter" }],
        "bodySize": 0
      }
    }
  ]
}

Notes

  • Request-only, by design. Field names and shapes follow HAR 1.2 so the output is familiar to HAR tooling, but httphq never observes a response — response, timings and cache are omitted rather than emitted as stubs that would read as captured data.
  • Global button is scoped to what's visible. It copies visibleRequests, so the method filter and search box double as a way to scope the export. The count in the label makes that scope visible; it's disabled at zero.
  • The existing headers/body copy links stay. This is additive.
  • Frontend only — no API, schema or Go changes. Everything needed is already in the client-side store.

Two properties worth knowing, both commented in public/har.js:

  • httpVersion is hardcoded to HTTP/1.1; the capture handler never records the protocol. Capturing it for real would need a new column on database.Request — separate change if it's wanted.
  • Header order is alphabetical, not wire order, because the capture handler flattens headers through a Go map and encoding/json sorts keys on marshal.

Testing

  • go test ./... passes (unaffected — no Go changes).
  • Playwright: 35/35 pass, including 5 new tests covering the per-card payload shape, the Copied! feedback, copy-all ordering (newest first), filter scoping, and the disabled-when-empty state.
  • Verified by hand in the browser against live captured GET/POST/PUT traffic.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LXy9D2BfSUqqj7BjPWs3fv

Getting a captured request out of the browser meant using the section-level
headers and body copy links and retyping the method, path and query string by
hand. Add a per-card "Copy request" button and a page-level "Copy all (N)" that
put the whole request on the clipboard as a HAR-shaped JSON document.

Entries follow HAR 1.2 field names and shapes so the output is familiar to HAR
tooling, but carry only a request: httphq never observes a response, so
response, timings and cache are omitted rather than emitted as stubs that would
read as captured data.

The global button copies the visible requests, so the method filter and search
box double as a way to scope the export; the count in its label makes that
scope visible.

Claude-Session: https://claude.ai/code/session_01LXy9D2BfSUqqj7BjPWs3fv
@botre
botre merged commit 9f07068 into master Aug 8, 2026
2 checks passed
@botre
botre deleted the feat/copy-requests-as-har branch August 8, 2026 09:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant